package net.zoneland.zrdp.generator.util;

import java.util.*;

import org.apache.commons.lang3.RegExUtils;

import net.zoneland.zrdp.common.constant.GenConstants;
import net.zoneland.zrdp.common.utils.StringUtilPlus;
import net.zoneland.zrdp.generator.config.GenConfig;
import net.zoneland.zrdp.generator.domain.GenTable;
import net.zoneland.zrdp.generator.domain.GenTableColumn;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

/**
 * 代码生成器 工具类
 *
 * @author zonevue
 */
public class GenUtils {
    private static final Map<String, String> HTML_TYPE_MAPPINGS;
    static {
        Map<String, String> aMap = new HashMap<>();
        aMap.put("status", GenConstants.HTML_RADIO);
        aMap.put("type", GenConstants.HTML_SELECT);
        aMap.put("sex", GenConstants.HTML_SELECT);
        aMap.put("image", GenConstants.HTML_IMAGE_UPLOAD);
        aMap.put("file", GenConstants.HTML_FILE_UPLOAD);
        aMap.put("content", GenConstants.HTML_EDITOR);
        HTML_TYPE_MAPPINGS = Collections.unmodifiableMap(aMap);
    }
    /**
     * 初始化表信息
     */
    public static void initTable(final GenTable genTable, final String operName) {
        genTable.setClassName(convertClassName(genTable.getTableName()));
        genTable.setPackageName(GenConfig.getPackageName());
        genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
        genTable.setFunctionName(replaceText(genTable.getTableComment()));
        genTable.setFunctionAuthor(GenConfig.getAuthor());
        genTable.setCreateBy(operName);
    }

    /**
     * 初始化列属性字段
     */
    public static void initColumnField(final GenTableColumn column, final GenTable table) {
        final String dataType = getDbType(column.getColumnType());
        final String columnName = column.getColumnName();
        column.setTableId(table.getTableId());
        column.setCreateBy(table.getCreateBy());
        // 设置java字段名
        column.setJavaField(StringUtilPlus.toCamelCase(columnName));
        // 设置默认类型
        column.setJavaType(GenConstants.TYPE_STRING);
        column.setQueryType(GenConstants.QUERY_EQ);

        if (listContains(GenConstants.COLUMNTYPE_STR, dataType) || listContains(GenConstants.COLUMNTYPE_TEXT, dataType)) {
            // 字符串长度超过500设置为文本域
            final Integer columnLength = getColumnLength(column.getColumnType());
            final String htmlType = columnLength >= 500 || listContains(GenConstants.COLUMNTYPE_TEXT, dataType) ?
                GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
            column.setHtmlType(htmlType);
        } else if (listContains(GenConstants.COLUMNTYPE_TIME, dataType)) {
            // 时间类型处理
            column.setJavaType(GenConstants.TYPE_DATETIME);
            if("date".equals(dataType)){
                column.setJavaType(GenConstants.TYPE_DATE);
            }else if ("time".equals(dataType)){
                column.setJavaType(GenConstants.TYPE_TIME);
            }
            column.setHtmlType(GenConstants.HTML_DATETIME);
        } else if (listContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
            // 数字类型处理
            column.setHtmlType(GenConstants.HTML_INPUT);
            // 如果是浮点型 统一用BigDecimal
            final String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
            } else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) { // 如果是整形
                column.setJavaType(GenConstants.TYPE_INTEGER);
            } else { // 长整形
                column.setJavaType(GenConstants.TYPE_LONG);
            }
        }

        // 插入字段（默认所有字段都需要插入）
        column.setIsInsert(GenConstants.REQUIRE);

        // 编辑字段
        if (!listContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) {
            column.setIsEdit(GenConstants.REQUIRE);
        }
        // 列表字段
        if (!listContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) {
            column.setIsList(GenConstants.REQUIRE);
        }
        // 查询字段
        if (!listContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) {
            column.setIsQuery(GenConstants.REQUIRE);
        }
        // 查询字段类型
        if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
            column.setQueryType(GenConstants.QUERY_LIKE);
        }
        // 设置页面上显示的html类型
        HTML_TYPE_MAPPINGS.entrySet().stream()
            .filter(entry -> StringUtils.endsWithIgnoreCase(columnName, entry.getKey()))
            .findFirst() // 从map中找到匹配的key，只匹配字段名的后面部分是否和key相等，最多只能找到一个
            .ifPresent(entry -> column.setHtmlType(entry.getValue()));

    }

    /**
     * 校验数组是否包含指定值
     *
     * @param arr 数组
     * @param targetValue 值
     * @return 是否包含
     */
    public static boolean arraysContains(final String[] arr, final String targetValue) {
        return Arrays.asList(arr).contains(targetValue);
    }

    /**
     * 校验List是否包含指定值
     *
     * @param list list
     * @param targetValue 值
     * @return 是否包含
     */
    public static boolean listContains(final List<String> list, final String targetValue) {
        return list.contains(targetValue);
    }

    /**
     * 获取模块名
     *
     * @param packageName 包名
     * @return 模块名
     */
    public static String getModuleName(final String packageName) {
        final int lastIndex = packageName.lastIndexOf(".");
        final int nameLength = packageName.length();
        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
    }

    /**
     * 获取业务名
     *
     * @param tableName 表名
     * @return 业务名
     */
    public static String getBusinessName(final String tableName) {
        final int lastIndex = tableName.lastIndexOf("_");
        final int nameLength = tableName.length();
        return StringUtils.substring(tableName, lastIndex + 1, nameLength);
    }

    /**
     * 表名转换成Java类名
     *
     * @param tableName 表名称
     * @return 类名
     */
    public static String convertClassName(final String tableName) {
        final boolean autoRemovePre = GenConfig.getAutoRemovePre();
        final String tablePrefix = GenConfig.getTablePrefix();
        if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) {
            final String[] searchList = StringUtils.split(tablePrefix, ",");
            final String newtableName = replaceFirst(tableName, searchList);
            return StringUtilPlus.convertToCamelCase(newtableName);
        }
        return StringUtilPlus.convertToCamelCase(tableName);
    }

    /**
     * 批量替换前缀
     *
     * @param replacementm 替换值
     * @param searchList 替换列表
     * @return 替换后的名字
     */
    public static String replaceFirst(final String replacementm, final String[] searchList) {
        for (final String searchString : searchList) {
            if (replacementm.startsWith(searchString)) {
                return replacementm.replaceFirst(searchString, "");
            }
        }
        return replacementm;
    }

    /**
     * 关键字替换
     *
     * @param text 需要被替换的名字
     * @return 替换后的名字
     */
    public static String replaceText(final String text) {
        return RegExUtils.replaceAll(text, "(?:表|基础开发框架)", "");
    }

    /**
     * 获取数据库类型字段
     *
     * @param columnType 列类型
     * @return 截取后的列类型
     */
    public static String getDbType(final String columnType) {
        if (StringUtils.indexOf(columnType, "(") > 0) {
            return StringUtils.substringBefore(columnType, "(");
        } else {
            return columnType;
        }
    }

    /**
     * 获取字段长度
     *
     * @param columnType 列类型
     * @return 截取后的列类型
     */
    public static Integer getColumnLength(final String columnType) {
        if (StringUtils.indexOf(columnType, "(") > 0) {
            final String length = StringUtils.substringBetween(columnType, "(", ")");
            return NumberUtils.toInt(length);
        } else {
            return 0;
        }
    }
}
